﻿//===============================================================================
// Microsoft Innovation Centre - Western Europe
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.ComponentModel;
using System.ServiceModel;
using System.Threading;
using Microsoft.WVB.Framework;
using Microsoft.WVB.Services.MicProfileService;

namespace Microsoft.WVB.Services
{
    public class MICProfileProvider : ProfileProvider<ProfileInfo>, IDisposable
    {
        private ProfileServiceClient _service = null;
        private SendOrPostCallback onGetProfileCompleted;
        private SendOrPostCallback onDeleteProfileCompleted;
        private SendOrPostCallback onUpdateProfileCompleted;
        private SendOrPostCallback onCreateProfileCompleted;

        public MICProfileProvider(string path) : base(path)
        {
            InitializeService();
        }
        
        private void InitializeService()
        {
            BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
            EndpointAddress address = new EndpointAddress(serviceRoot);
            _service = new ProfileServiceClient(binding, address);

            InitializeDelegates();
        }

        private void InitializeDelegates()
        {
            Action<object> raiseGetProfileCompleted = o =>
            {
                AcquireCompletedEventArgs<ProfileInfo> e = o as AcquireCompletedEventArgs<ProfileInfo>;
                if (e != null)
                    OnGetProfileCompleted(e);
            };
            onGetProfileCompleted = new SendOrPostCallback(raiseGetProfileCompleted);

            Action<object> raiseDeleteProfileCompleted = o =>
            {
                NotifyActionCompletedEventArgs e = o as NotifyActionCompletedEventArgs;
                if (e != null)
                    OnDeleteProfileCompleted(e);
            };
            onDeleteProfileCompleted = new SendOrPostCallback(raiseDeleteProfileCompleted);

            Action<object> raiseUpdateProfileCompleted = o =>
            {
                NotifyActionCompletedEventArgs e = o as NotifyActionCompletedEventArgs;
                if (e != null)
                    OnUpdateProfileCompleted(e);
            };
            onUpdateProfileCompleted = new SendOrPostCallback(raiseUpdateProfileCompleted);

            Action<object> raiseCreateProfileCompleted = o =>
            {
                AcquireCompletedEventArgs<ProfileInfo> e = o as AcquireCompletedEventArgs<ProfileInfo>;
                if (e != null)
                    OnCreateProfileCompleted(e);
            };
            onCreateProfileCompleted = new SendOrPostCallback(raiseCreateProfileCompleted);

        }

        public override void GetProfileAsync(string username, object userData)
        {
            GetProfileRequest req = new GetProfileRequest();
            req.Username = username;

            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);
            AsyncCallback ac = null;

            ac = iAsyncResult =>
            {
                AcquireCompletedEventArgs<ProfileInfo> args = null;
                GetProfileResponse response = null;
                WVBServiceException e = null;
                ProfileInfo profile = null;

                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;

                try
                {
                    aop.SynchronizationContext.OperationStarted();
                    response = ((IProfileService)_service).EndGetProfile(iAsyncResult);
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICProfileProvider.GetProfileAsync", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICProfileProvider.GetProfileAsync", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "GetProfileAsync"), "CommunicationException", "MICProfileProvider.GetProfileAsync", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "GetProfileAsync"), "Unknown", "MICProfileProvider.GetProfileAsync", generalException);
                }

                if ((response != null) && (response.Profile != null))
                {
                    profile = EntityConverter.ConvertToProfileInfo(response.Profile);
                }

                args = new AcquireCompletedEventArgs<ProfileInfo>(profile, e, false, aop.UserSuppliedState);
                aop.PostOperationCompleted(onGetProfileCompleted, args);
            };

            ((IProfileService)_service).BeginGetProfile(req, ac, op);
        }

        public override void CreateProfileAsync(ProfileInfo profile, object userData)
        {
            CreateProfileRequest req = new CreateProfileRequest();
            req.Profile = EntityConverter.ConvertToWVBProfile(profile);

            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);
            AsyncCallback ac = null;
            ProfileInfo p = null;

            ac = iAsyncResult =>
            {
                AcquireCompletedEventArgs<ProfileInfo> args = null;
                CreateProfileResponse response = null;
                WVBServiceException e = null;

                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;

                try
                {
                    aop.SynchronizationContext.OperationStarted();
                    response = ((IProfileService)_service).EndCreateProfile(iAsyncResult);
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICProfileProvider.CreateProfile", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICProfileProvider.CreateProfile", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "CreateProfileAsync"), "CommunicationException", "MICProfileProvider.CreateProfile", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "CreateProfileAsync"), "Unknown", "MICProfileProvider.CreateProfile", generalException);
                }

                if ((response != null) && (response.Profile != null))
                {
                    p = EntityConverter.ConvertToProfileInfo(response.Profile);
                }
                else
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "CreateProfileAsync"), "Unknown", "MICProfileProvider.CreateProfile", new NullReferenceException());

                args = new AcquireCompletedEventArgs<ProfileInfo>(p, e, false, aop.UserSuppliedState);
                aop.PostOperationCompleted(onCreateProfileCompleted, args);
            };

            ((IProfileService)_service).BeginCreateProfile(req, ac, op);
        }

        public override void DeleteProfileAsync(string username, object userData)
        {
            DeleteProfileRequest req = new DeleteProfileRequest();
            req.UserName = username;

            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);
            AsyncCallback ac = null;

            ac = iAsyncResult =>
            {
                NotifyActionCompletedEventArgs args = null;
                DeleteProfileResponse response = null;
                WVBServiceException e = null;

                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;

                try
                {
                    aop.SynchronizationContext.OperationStarted();
                    response = ((IProfileService)_service).EndDeleteProfile(iAsyncResult);
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICProfileProvider.DeleteProfileAsync", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICProfileProvider.DeleteProfileAsync", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "DeleteProfileAsync"), "CommunicationException", "MICProfileProvider.DeleteProfileAsync", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "DeleteProfileAsync"), "Unknown", "MICProfileProvider.DeleteProfileAsync", generalException);
                }

                if (response != null)
                    args = new NotifyActionCompletedEventArgs(response.Succeed, Microsoft.WVB.Framework.Action.Delete, e, false, aop.UserSuppliedState);
                else
                {
                    e = new WVBServiceException(Strings.WCF_Services_Exception_InternalServerError, Strings.MICProfileProvider_Exception_Serialization, "MICProfileProvider.DeleteProfileAsync", new NullReferenceException());
                    args = new NotifyActionCompletedEventArgs(false, Microsoft.WVB.Framework.Action.Delete, e, false, aop.UserSuppliedState);
                }

                aop.PostOperationCompleted(onDeleteProfileCompleted, args);
            };

            ((IProfileService)_service).BeginDeleteProfile(req, ac, op);
        }

        public override void UpdateProfileAsync(ProfileInfo profile, object userData)
        {
            UpdateProfileRequest req = new UpdateProfileRequest();
            req.Profile = EntityConverter.ConvertToWVBProfile(profile);

            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);
            AsyncCallback ac = null;

            ac = iAsyncResult =>
            {
                NotifyActionCompletedEventArgs args = null;
                UpdateProfileResponse response = null;
                WVBServiceException e = null;

                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;

                try
                {
                    aop.SynchronizationContext.OperationStarted();
                    response = ((IProfileService)_service).EndUpdateProfile(iAsyncResult);
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICProfileProvider.UpdateProfileAsync", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICProfileProvider.UpdateProfileAsync", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "UpdateProfileAsync"), "CommunicationException", "MICProfileProvider.UpdateProfileAsync", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "UpdateProfileAsync"), "Unknown", "MICProfileProvider.UpdateProfileAsync", generalException);
                }

                if (response != null)
                    args = new NotifyActionCompletedEventArgs(response.Succeed, Microsoft.WVB.Framework.Action.Update, e, false, aop.UserSuppliedState);
                else
                {
                    e = new WVBServiceException(Strings.WCF_Services_Exception_InternalServerError, Strings.MICProfileProvider_Exception_Serialization, "MICProfileProvider.UpdateProfileAsync", new NullReferenceException());
                    args = new NotifyActionCompletedEventArgs(false, Microsoft.WVB.Framework.Action.Update, e, false, aop.UserSuppliedState);
                }

                aop.PostOperationCompleted(onUpdateProfileCompleted, args);
            };

            ((IProfileService)_service).BeginUpdateProfile(req, ac, op);
        }

        public override void CancelAsynch()
        {
           // not implemented
        }

        #region IDisposable Members

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
